﻿#ifndef			_XANADU_CORE_BYTE_ARRAY_H_
#define			_XANADU_CORE_BYTE_ARRAY_H_

#include <XanaduCore/XHeader.h>
#include <XanaduCore/XAllocator.h>

/// <summary>
/// A byte array tool
/// </summary>
class XANADU_CORE_EXPORT XByteArray final : private XAllocator
{
public:
	using				_Elem = XAllocator::_Elem;
	using				size_type = XAllocator::size_type;

public:
	static const size_type		npos = XAllocator::npos;

public:
	// constructor
	XByteArray() noexcept;

	// constructor
	XByteArray(const _Elem* _Memory) noexcept;

	// constructor
	XByteArray(const _Elem* _Memory, size_type _Length) noexcept;

	// constructor
	XByteArray(size_type _Size, _Elem _Char) noexcept;

	// constructor
	XByteArray(const XByteArray& _Bytes) noexcept;

	// destructor
	~XByteArray() noexcept override;

public:
	// operators overload =
	XByteArray& operator = (const _Elem* _Memory) noexcept;

	// operators overload =
	XByteArray& operator = (const XByteArray& _Bytes) noexcept;

	// operators overload =
	XByteArray& operator = (XByteArray&& _Other) noexcept;

public:
	// operators overload +
	XByteArray operator + (_Elem _Char) const noexcept;

	// operators overload +
	XByteArray operator + (const _Elem* _Memory) const noexcept;

	// operators overload +
	XByteArray operator + (const XByteArray& _Bytes) const noexcept;

public:
	// operators overload +=
	XByteArray& operator += (_Elem _Char) noexcept;

	// operators overload +=
	XByteArray& operator += (const _Elem* _Memory) noexcept;

	// operators overload +=
	XByteArray& operator += (const XByteArray& _Bytes) noexcept;

public:
	// operators overload ==
	bool operator == (const _Elem* _Memory) const noexcept;

	// operators overload ==
	bool operator == (const XByteArray& _Bytes) const noexcept;

	// operators overload !=
	bool operator != (const _Elem* _Memory) const noexcept;

	// operators overload !=
	bool operator != (const XByteArray& _Bytes) const noexcept;

	// operators overload <
	bool operator < (const _Elem* _Memory)const noexcept;

	// operators overload <
	bool operator < (const XByteArray& _Bytes)const noexcept;

	// operators overload >
	bool operator > (const _Elem* _Memory) const noexcept;

	// operators overload >
	bool operator > (const XByteArray& _Bytes) const noexcept;

	// operators overload <=
	bool operator <= (const _Elem* _Memory) const noexcept;

	// operators overload <=
	bool operator <= (const XByteArray& _Bytes) const noexcept;

	// operators overload >=
	bool operator >= (const _Elem* _Memory) const noexcept;

	// operators overload >=
	bool operator >= (const XByteArray& _Bytes) const noexcept;

public:
	// 获取数据指针
	_Elem* data() noexcept;

	// 获取常量数据指针
	const _Elem* data() const noexcept;

	// 获取数据长度
	size_type size() const noexcept;

	// 获取数据长度
	size_type length() const noexcept;

	// Resizing
	void resize(size_type _Size) noexcept;

	// 从 _Index 截断字节数组的下标位置。如果 _Index 超出了数组的末尾，则什么也不会发生。
	void truncate(size_type _Index) noexcept;

	// 填充一个字符到指定长度的空格，如果是 XByteArray::npos ，则全部填充
	XByteArray& fill(_Elem _Char, size_type _Size = XByteArray::npos) noexcept;

	// 获取当前容量
	size_type capacity() const noexcept;

	// Check whether it is empty, and return true when the length is 0
	bool empty() const noexcept;

	// Check whether there is a value, and return true when the length is not 0
	bool exist() const noexcept;

	// clear
	void clear() noexcept;

public:
	// 按下标读取数据
	_Elem at(size_type _Index) const noexcept;

	// 得到第一位的数据
	_Elem front() const noexcept;

	// 得到第一位的数据
	_Elem& front() noexcept;

	// 得到最后一位的数据
	_Elem back() const noexcept;

	// 得到最后一位的数据
	_Elem& back() noexcept;

	// 按下标读取数据
	_Elem& operator[](size_type _Index) noexcept;

	// 按下标读取数据
	_Elem operator[](size_type _Index) const noexcept;

public:
	// Iterator type definition
	typedef _Elem*					iterator;
	typedef const _Elem*				const_iterator;
	typedef iterator				Iterator;
	typedef const_iterator				ConstIterator;
	typedef std::reverse_iterator<iterator>		reverse_iterator;
	typedef std::reverse_iterator<const_iterator>	const_reverse_iterator;

	// 迭代器操作
	iterator begin() noexcept;

	// 迭代器操作
	const_iterator begin() const noexcept;

	// 迭代器操作
	const_iterator cbegin() const noexcept;

	// 迭代器操作
	const_iterator constBegin() const noexcept;

	// 迭代器操作
	iterator end() noexcept;

	// 迭代器操作
	const_iterator end() const noexcept;

	// 迭代器操作
	const_iterator cend() const noexcept;

	// 迭代器操作
	const_iterator constEnd() const noexcept;

	// 迭代器操作
	reverse_iterator rbegin() noexcept;

	// 迭代器操作
	reverse_iterator rend() noexcept;

	// 迭代器操作
	const_reverse_iterator rbegin() const noexcept;

	// 迭代器操作
	const_reverse_iterator rend() const noexcept;

	// 迭代器操作
	const_reverse_iterator crbegin() const noexcept;

	// 迭代器操作
	const_reverse_iterator crend() const noexcept;

public:
	// Vector兼容:Add at the end
	void push_back(_Elem _Char) noexcept;

	// Vector兼容:Add at the end
	void push_back(const _Elem* _Memory) noexcept;

	// Vector兼容:Add at the end
	void push_back(const XByteArray& _Bytes) noexcept;

	// Vector兼容:从开头添加数据
	void push_front(_Elem _Char) noexcept;

	// Vector兼容:从开头添加数据
	void push_front(const _Elem* _Memory) noexcept;

	// Vector兼容:从开头添加数据
	void push_front(const XByteArray& _Bytes) noexcept;

public:
	// 从开头添加数据
	XByteArray& prepend(_Elem _Char) noexcept;

	// 从开头添加数据
	XByteArray& prepend(size_type _Count, _Elem _Char) noexcept;

	// 从开头添加数据
	XByteArray& prepend(const _Elem* _String) noexcept;

	// 从开头添加数据
	XByteArray& prepend(const _Elem* _String, size_type _Length) noexcept;

	// 从开头添加数据
	XByteArray& prepend(const XByteArray& _Bytes) noexcept;

	// Add at the end
	XByteArray& append(_Elem _Char) noexcept;

	// Add at the end
	XByteArray& append(size_type _Count, _Elem _Char) noexcept;

	// Add at the end
	XByteArray& append(const _Elem* _String) noexcept;

	// Add at the end
	XByteArray& append(const _Elem* _String, size_type _Length) noexcept;

	// Add at the end
	XByteArray& append(const XByteArray& _Bytes) noexcept;

	// Inserts data from the specified location
	XByteArray& insert(size_type _Index, _Elem _Char) noexcept;

	// Inserts data from the specified location
	XByteArray& insert(size_type _Index, size_type _Count, _Elem _Char) noexcept;

	// Inserts data from the specified location
	XByteArray& insert(size_type _Index, const _Elem* _String) noexcept;

	// Inserts data from the specified location
	XByteArray& insert(size_type _Index, const _Elem* _String, size_type _Length) noexcept;

	// Inserts data from the specified location
	XByteArray& insert(size_type _Index, const XByteArray& _Bytes) noexcept;

public:
	// Removes the specified length of data from the specified location
	XByteArray& remove(size_type _Index, size_type _Length) noexcept;

	// Delete the same data as the parameter
	XByteArray& remove(_Elem _Char) noexcept;

	// Delete the same data as the parameter
	XByteArray& remove(const _Elem* _Memory) noexcept;

	// Delete the same data as the parameter
	XByteArray& remove(const _Elem* _Memory, size_type _Size) noexcept;

	// Delete the same data as the parameter
	XByteArray& remove(const XByteArray& _Bytes) noexcept;

public:
	// Replace the specified data
	XByteArray& replace(size_type _Index, size_type _Length, const _Elem* _After) noexcept;

	// Replace the specified data
	XByteArray& replace(size_type _Index, size_type _Length, const _Elem* _After, size_type _Asize) noexcept;

	// Replace the specified data
	XByteArray& replace(size_type _Index, size_type _Length, const XByteArray& _Bytes) noexcept;

	// Replace the specified data
	XByteArray& replace(_Elem _Before, const _Elem* _After) noexcept;

	// Replace the specified data
	XByteArray& replace(_Elem _Before, const XByteArray& _After) noexcept;

	// Replace the specified data
	XByteArray& replace(const _Elem* _Before, const _Elem* _After) noexcept;

	// Replace the specified data
	XByteArray& replace(const _Elem* _Before, size_type _Bsize, const _Elem* _After, size_type _Asize) noexcept;

	// Replace the specified data
	XByteArray& replace(const XByteArray& _Before, const XByteArray& _After) noexcept;

	// Replace the specified data
	XByteArray& replace(const XByteArray& _Before, const _Elem* _After) noexcept;

	// Replace the specified data
	XByteArray& replace(const _Elem* _Before, const XByteArray& _After) noexcept;

	// Replace the specified data
	XByteArray& replace(_Elem _Before, _Elem _After) noexcept;

public:
	// 按长度获取左边的数据
	XByteArray left(size_type _Length) const noexcept;

	// 按长度获取右边的数据
	XByteArray right(size_type _Length) const noexcept;

	// 按长度获取中间的数据
	XByteArray mid(size_type _Index, size_type _Length = XByteArray::npos) const noexcept;

public:
	// 倒序
	XByteArray& reverse() noexcept;

	// 倒序
	XByteArray reverse() const noexcept;

public:
	// 检查头部是否相同
	bool startsWith(_Elem _Char) const noexcept;

	// 检查头部是否相同
	bool startsWith(const _Elem* _Memory) const noexcept;

	// 检查头部是否相同
	bool startsWith(const XByteArray& _Bytes) const noexcept;

	// 检查尾部是否相同
	bool endsWith(_Elem _Char) const noexcept;

	// 检查尾部是否相同
	bool endsWith(const _Elem* _Memory) const noexcept;

	// 检查尾部是否相同
	bool endsWith(const XByteArray& _Bytes) const noexcept;

public:
	// Find in positive order from the specified location
	size_type find(_Elem _Char, size_type _From = 0U) const noexcept;

	// Find in positive order from the specified location
	size_type find(const _Elem* _Memory, size_type _From = 0U) const noexcept;

	// Find in positive order from the specified location
	size_type find(const XByteArray& _Bytes, size_type _From = 0U) const noexcept;

	// Search in reverse order from the specified location
	size_type rfind(_Elem _Char, size_type _From = XByteArray::npos) const noexcept;

	// Search in reverse order from the specified location
	size_type rfind(const _Elem* _Memory, size_type _From = XByteArray::npos) const noexcept;

	// Search in reverse order from the specified location
	size_type rfind(const XByteArray& _Bytes, size_type _From = XByteArray::npos) const noexcept;

public:
	// Check whether the specified content is included
	bool contains(_Elem _Char) const noexcept;

	// Check whether the specified content is included
	bool contains(const _Elem* _Memory) const noexcept;

	// Check whether the specified content is included
	bool contains(const XByteArray& _Bytes) const noexcept;

	// Check that they are the same
	int compare(const _Elem* _Memory, Xanadu::CaseSensitivity _XCS = Xanadu::CaseSensitive) const noexcept;

	// Check that they are the same
	int compare(const XByteArray& _Bytes, Xanadu::CaseSensitivity _XCS = Xanadu::CaseSensitive) const noexcept;

public:
	// 检查是否全部是小写字符
	bool isLower() const noexcept;

	// 检查是否全部是大写字符
	bool isUpper() const noexcept;

	// Convert to lowercase
	XByteArray toLower() const noexcept;

	// Convert to uppercase
	XByteArray toUpper() const noexcept;

	// 删除开始和结束空白字符
	XByteArray trimmed() const noexcept;

	// 删除开头、中间和结尾空白字符
	XByteArray simplified() const noexcept;

public:
	// 判断字符是否是空白字符 ('\t','\n','\v','\f','\r','_') 中的一个
	static bool isSpace(_Elem _Char) noexcept;

	// 格式化 ByteArray (_Elem* [%s]) (w_Elem_t* [%ls])
	static XByteArray format(const _Elem* _Format, ...) noexcept;

public:
	// Splits an array by the specified data
	std::list<XByteArray> split(_Elem _Char) const noexcept;

	// Splits an array by the specified data
	std::list<XByteArray> split(const _Elem* _Memory) const noexcept;

	// Splits an array by the specified data
	std::list<XByteArray> split(const _Elem* _Memory, size_type _Size) const noexcept;

	// Splits an array by the specified data
	std::list<XByteArray> split(const XByteArray& _Bytes) const noexcept;

public:
	// Convert to Base64
	XByteArray toBase64() const noexcept;

	// Convert to HEX, default uppercase
	XByteArray toHex() const noexcept;

	// Building objects from memory
	static XByteArray fromMemory(const _Elem* _Memory, size_type _Size) noexcept;

	// Building objects from Base64
	static XByteArray fromBase64(const void* _Memory, size_type _Size) noexcept;

	// Building objects from Base64
	static XByteArray fromBase64(const XByteArray& _Bytes) noexcept;

	// Building objects from HEX
	static XByteArray fromHex(const void* _Memory, size_type _Size = XByteArray::npos) noexcept;

	// Building objects from HEX
	static XByteArray fromHex(const XByteArray& _Bytes) noexcept;
};

#endif
